<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id: Think.class.php 2793 2012-03-02 05:34:40Z liu21st $

/**
 +------------------------------------------------------------------------------
 * ThinkPHP Portal类
 +------------------------------------------------------------------------------
 * @category   Think
 * @package  Think
 * @subpackage  Core
 * @author    liu21st <liu21st@gmail.com>
 * @version   $Id: Think.class.php 2793 2012-03-02 05:34:40Z liu21st $
 +------------------------------------------------------------------------------
 */
class Think {

	private static $_instance = array();

	/**
	 +----------------------------------------------------------
	 * 应用程序初始化
	 +----------------------------------------------------------
	 * @access public
	 +----------------------------------------------------------
	 * @return void
	 +----------------------------------------------------------
	 */
	static public function Start() {
		// 设定错误和异常处理
		set_error_handler(array('Think','appError'));
		set_exception_handler(array('Think','appException'));
		// 注册AUTOLOAD方法
		spl_autoload_register(array('Think', 'autoload'));
		//[RUNTIME]
		Think::buildApp();         // 预编译项目
		//[/RUNTIME]
		// 运行应用
		App::run();
		return ;
	}

	//[RUNTIME]
	/**
	 +----------------------------------------------------------
	 * 读取配置信息 编译项目
	 +----------------------------------------------------------
	 * @access private
	 +----------------------------------------------------------
	 * @return string
	 +----------------------------------------------------------
	 */
	static private function buildApp() {
		// 加载底层惯例配置文件
		C(include THINK_PATH.'Conf/convention.php');

		// 读取运行模式
		if(defined('MODE_NAME')) { // 模式的设置并入核心模式
			$mode   = include MODE_PATH.strtolower(MODE_NAME).'.php';
		}else{
			$mode   =  array();
		}

		// 加载模式配置文件
		if(isset($mode['config'])) {
			C( is_array($mode['config'])?$mode['config']:include $mode['config'] );
		}

		// 加载项目配置文件
		if(is_file(CONF_PATH.'config.php'))
		C(include CONF_PATH.'config.php');
		//[sae]惯例配置
		C(include SAE_PATH.'Conf/convention_sae.php');
		//[sae]专有配置
		if (is_file(CONF_PATH . 'config_sae.php'))
		C(include CONF_PATH . 'config_sae.php');
		// 加载框架底层语言包
		L(include THINK_PATH.'Lang/'.strtolower(C('DEFAULT_LANG')).'.php');

		// 加载模式系统行为定义
		if(C('APP_TAGS_ON')) {
			if(isset($mode['extends'])) {
				C('extends',is_array($mode['extends'])?$mode['extends']:include $mode['extends']);
			}else{ //[sae] 默认加载系统行为扩展定义
				C('extends', include SAE_PATH.'Conf/tags.php');
			}
		}

		// 加载应用行为定义
		if(isset($mode['tags'])) {
			C('tags', is_array($mode['tags'])?$mode['tags']:include $mode['tags']);
		}elseif(is_file(CONF_PATH.'tags.php')){
			// 默认加载项目配置目录的tags文件定义
			C('tags', include CONF_PATH.'tags.php');
		}

		$compile   = '';
		// 读取核心编译文件列表
		if(isset($mode['core'])) {
			$list   =  $mode['core'];
		}else{
			$list  =  array(
			SAE_PATH.'Common/functions.php', //[sae] 标准模式函数库
			SAE_PATH.'Common/sae_functions.php',//[sae]新增sae专用函数
			SAE_PATH.'Lib/Core/Log.class.php',    // 日志处理类
			CORE_PATH.'Core/Dispatcher.class.php', // URL调度类
			CORE_PATH.'Core/App.class.php',   // 应用程序类
			SAE_PATH.'Lib/Core/Action.class.php', //[sae] 控制器类
			CORE_PATH.'Core/View.class.php',  // 视图类
			);
		}
		// 项目追加核心编译列表文件
		if(is_file(CONF_PATH.'core.php')) {
			$list  =  array_merge($list,include CONF_PATH.'core.php');
		}
		foreach ($list as $file){
			if(is_file($file))  {
				require_cache($file);
				if(!APP_DEBUG)   $compile .= compile($file);
			}
		}

		// 加载项目公共文件
		if(is_file(COMMON_PATH.'common.php')) {
			include COMMON_PATH.'common.php';
			// 编译文件
			if(!APP_DEBUG)  $compile   .= compile(COMMON_PATH.'common.php');
		}

		// 加载模式别名定义
		if(isset($mode['alias'])) {
			$alias = is_array($mode['alias'])?$mode['alias']:include $mode['alias'];
			alias_import($alias);
			if(!APP_DEBUG) $compile .= 'alias_import('.var_export($alias,true).');';
		}
		// 加载项目别名定义
		if(is_file(CONF_PATH.'alias.php')){
			$alias = include CONF_PATH.'alias.php';
			alias_import($alias);
			if(!APP_DEBUG) $compile .= 'alias_import('.var_export($alias,true).');';
		}

		if(APP_DEBUG) {
			// 调试模式加载系统默认的配置文件
			C(include THINK_PATH.'Conf/debug.php');
			// 读取调试模式的应用状态
			$status  =  C('APP_STATUS');
			// 加载对应的项目配置文件
			if(is_file(CONF_PATH.$status.'.php'))
			// 允许项目增加开发模式配置定义
			C(include CONF_PATH.$status.'.php');
		}else{
			// 部署模式下面生成编译文件
			build_runtime_cache($compile);
		}
		return ;
	}
	//[/RUNTIME]

	/**
	 +----------------------------------------------------------
	 * 系统自动加载ThinkPHP类库
	 * 并且支持配置自动加载路径
	 +----------------------------------------------------------
	 * @param string $class 对象类名
	 +----------------------------------------------------------
	 * @return void
	 +----------------------------------------------------------
	 */
	public static function autoload($class) {
		// 检查是否存在别名定义
		if(alias_import($class)) return ;

		if(substr($class,-8)=='Behavior') { // 加载行为
			if(require_cache(CORE_PATH.'Behavior/'.$class.'.class.php')
			|| require_cache(EXTEND_PATH.'Behavior/'.$class.'.class.php')
			|| require_cache(LIB_PATH.'Behavior/'.$class.'.class.php')
			|| (defined('MODE_NAME') && require_cache(MODE_PATH.ucwords(MODE_NAME).'/Behavior/'.$class.'.class.php'))) {
				return ;
			}
		}elseif(substr($class,-5)=='Model'){ // 加载模型
			if(require_cache(LIB_PATH.'Model/'.$class.'.class.php')
			|| require_cache(EXTEND_PATH.'Model/'.$class.'.class.php') ) {
				return ;
			}
		}elseif(substr($class,-6)=='Action'){ // 加载控制器
			if((defined('GROUP_NAME') && require_cache(LIB_PATH.'Action/'.GROUP_NAME.'/'.$class.'.class.php'))
			|| require_cache(LIB_PATH.'Action/'.$class.'.class.php')
			|| require_cache(EXTEND_PATH.'Action/'.$class.'.class.php') ) {
				return ;
			}
		}

		// 根据自动加载路径设置进行尝试搜索
		$paths  =   explode(',',C('APP_AUTOLOAD_PATH'));
		foreach ($paths as $path){
			if(import($path.'.'.$class))
			// 如果加载类成功则返回
			return ;
		}
	}

	/**
	 +----------------------------------------------------------
	 * 取得对象实例 支持调用类的静态方法
	 +----------------------------------------------------------
	 * @param string $class 对象类名
	 * @param string $method 类的静态方法名
	 +----------------------------------------------------------
	 * @return object
	 +----------------------------------------------------------
	 */
	static public function instance($class,$method='') {
		$identify   =   $class.$method;
		if(!isset(self::$_instance[$identify])) {
			if(class_exists($class)){
				$o = new $class();
				if(!empty($method) && method_exists($o,$method))
				self::$_instance[$identify] = call_user_func_array(array(&$o, $method));
				else
				self::$_instance[$identify] = $o;
			}
			else
			halt(L('_CLASS_NOT_EXIST_').':'.$class);
		}
		return self::$_instance[$identify];
	}

	/**
	 +----------------------------------------------------------
	 * 自定义异常处理
	 +----------------------------------------------------------
	 * @access public
	 +----------------------------------------------------------
	 * @param mixed $e 异常对象
	 +----------------------------------------------------------
	 */
	static public function appException($e) {
		halt($e->__toString());
	}

	/**
	 +----------------------------------------------------------
	 * 自定义错误处理
	 +----------------------------------------------------------
	 * @access public
	 +----------------------------------------------------------
	 * @param int $errno 错误类型
	 * @param string $errstr 错误信息
	 * @param string $errfile 错误文件
	 * @param int $errline 错误行数
	 +----------------------------------------------------------
	 * @return void
	 +----------------------------------------------------------
	 */
	static public function appError($errno, $errstr, $errfile, $errline) {
		switch ($errno) {
			case E_ERROR:
			case E_USER_ERROR:
				$errorStr = "[$errno] $errstr ".basename($errfile)." 第 $errline 行.";
				if(C('LOG_RECORD')) Log::write($errorStr,Log::ERR);
				halt($errorStr);
				break;
			case E_STRICT:
			case E_USER_WARNING:
			case E_USER_NOTICE:
			default:
				$errorStr = "[$errno] $errstr ".basename($errfile)." 第 $errline 行.";
				Log::record($errorStr,Log::NOTICE);
				break;
		}
	}

	/**
	 +----------------------------------------------------------
	 * 自动变量设置
	 +----------------------------------------------------------
	 * @access public
	 +----------------------------------------------------------
	 * @param $name 属性名称
	 * @param $value  属性值
	 +----------------------------------------------------------
	 */
	public function __set($name ,$value) {
		if(property_exists($this,$name))
		$this->$name = $value;
	}

	/**
	 +----------------------------------------------------------
	 * 自动变量获取
	 +----------------------------------------------------------
	 * @access public
	 +----------------------------------------------------------
	 * @param $name 属性名称
	 +----------------------------------------------------------
	 * @return mixed
	 +----------------------------------------------------------
	 */
	public function __get($name) {
		return isset($this->$name)?$this->$name:null;
	}
}